/**
 * 小程序专用视频缓存服务
 * 针对小程序的限制和特性进行优化
 * 支持微信小程序、支付宝小程序等
 */

class MiniProgramVideoCacheService {
  constructor() {
    this.cacheMap = new Map(); // 缓存映射表
    this.downloadingMap = new Map(); // 下载进度映射表
    this.tempFileMap = new Map(); // 临时文件映射表
    
    // 小程序限制配置
    this.maxCacheSize = 20 * 1024 * 1024; // 20MB缓存限制
    this.maxCacheCount = 8; // 最多8个视频文件
    this.tempFileExpire = 2 * 60 * 60 * 1000; // 临时文件2小时过期
    
    // 存储配置
    this.cacheStorageKey = 'mp_video_cache';
    this.tempFileStorageKey = 'mp_temp_files';
    
    // 下载配置
    this.maxConcurrentDownloads = 2; // 最大并发下载数
    this.downloadTimeout = 15000; // 15秒下载超时
    this.retryAttempts = 2; // 重试次数
    
    // 当前下载任务
    this.activeDownloads = 0;
    this.downloadQueue = [];
    
    // 性能监控
    this.performanceMetrics = {
      cacheHits: 0,
      cacheMisses: 0,
      downloadSuccesses: 0,
      downloadFailures: 0,
      totalDownloadTime: 0
    };
    
    console.log('[小程序缓存] 服务初始化');
  }

  /**
   * 初始化缓存服务
   */
  async init() {
    try {
      console.log('[小程序缓存] 开始初始化...');
      
      // 从本地存储恢复缓存数据
      await this.loadCacheFromStorage();
      
      // 验证临时文件有效性
      await this.validateTempFiles();
      
      // 清理过期缓存
      await this.cleanExpiredCache();
      
      // 启动定时清理
      this.startPeriodicCleanup();
      
      console.log(`[小程序缓存] 初始化完成，当前缓存: ${this.cacheMap.size} 个文件`);
      
    } catch (error) {
      console.error('[小程序缓存] 初始化失败:', error);
    }
  }

  /**
   * 缓存视频
   */
  async cache(videoUrl, options = {}) {
    const {
      priority = 1,
      size = '未知',
      quality = 'normal',
      timeout = this.downloadTimeout
    } = options;

    // 检查是否已缓存
    if (this.cacheMap.has(videoUrl)) {
      const cacheInfo = this.cacheMap.get(videoUrl);
      if (await this.isTempFileValid(cacheInfo)) {
        this.performanceMetrics.cacheHits++;
        console.log(`[小程序缓存] 缓存命中: ${videoUrl}`);
        return cacheInfo.tempFilePath;
      } else {
        // 缓存无效，删除
        await this.removeFromCache(videoUrl);
      }
    }

    // 检查是否正在下载
    if (this.downloadingMap.has(videoUrl)) {
      console.log(`[小程序缓存] 视频下载中: ${videoUrl}`);
      return await this.downloadingMap.get(videoUrl);
    }

    // 检查下载队列
    if (this.activeDownloads >= this.maxConcurrentDownloads) {
      console.log(`[小程序缓存] 下载队列已满，等待中: ${videoUrl}`);
      return await this.queueDownload(videoUrl, options);
    }

    // 立即开始下载
    return await this.startDownload(videoUrl, options);
  }

  /**
   * 开始下载视频
   */
  async startDownload(videoUrl, options) {
    const downloadPromise = this.downloadVideo(videoUrl, options);
    this.downloadingMap.set(videoUrl, downloadPromise);

    try {
      const result = await downloadPromise;
      this.downloadingMap.delete(videoUrl);
      this.processDownloadQueue(); // 处理队列中的下载
      return result;
    } catch (error) {
      this.downloadingMap.delete(videoUrl);
      this.processDownloadQueue();
      throw error;
    }
  }

  /**
   * 队列下载
   */
  async queueDownload(videoUrl, options) {
    return new Promise((resolve, reject) => {
      this.downloadQueue.push({
        videoUrl,
        options,
        resolve,
        reject
      });
    });
  }

  /**
   * 处理下载队列
   */
  async processDownloadQueue() {
    if (this.downloadQueue.length === 0 || this.activeDownloads >= this.maxConcurrentDownloads) {
      return;
    }

    const { videoUrl, options, resolve, reject } = this.downloadQueue.shift();
    
    try {
      const result = await this.startDownload(videoUrl, options);
      resolve(result);
    } catch (error) {
      reject(error);
    }
  }

  /**
   * 下载视频文件
   */
  async downloadVideo(videoUrl, options) {
    const { timeout = this.downloadTimeout } = options;
    
    this.activeDownloads++;
    const startTime = Date.now();

    try {
      console.log(`[小程序缓存] 开始下载: ${videoUrl}`);
      
      // 确保有足够的缓存空间
      await this.ensureCacheSpace();

      // 小程序下载
      const tempFilePath = await this.downloadWithUni(videoUrl, timeout);
      
      // 保存缓存信息
      const cacheInfo = {
        url: videoUrl,
        tempFilePath: tempFilePath,
        createdAt: Date.now(),
        lastAccessed: Date.now(),
        accessCount: 1,
        size: options.size,
        quality: options.quality
      };

      this.cacheMap.set(videoUrl, cacheInfo);
      
      // 保存到本地存储
      await this.saveCacheToStorage();

      const downloadTime = Date.now() - startTime;
      this.updatePerformanceMetrics(downloadTime, true);

      console.log(`[小程序缓存] 下载完成: ${videoUrl}, 耗时: ${downloadTime}ms`);
      
      this.performanceMetrics.downloadSuccesses++;
      return tempFilePath;

    } catch (error) {
      const downloadTime = Date.now() - startTime;
      this.updatePerformanceMetrics(downloadTime, false);
      this.performanceMetrics.downloadFailures++;
      
      console.error(`[小程序缓存] 下载失败: ${videoUrl}`, error);
      throw error;
    } finally {
      this.activeDownloads--;
    }
  }

  /**
   * 使用uni-app下载
   */
  async downloadWithUni(videoUrl, timeout) {
    return new Promise((resolve, reject) => {
      const downloadTask = uni.downloadFile({
        url: videoUrl,
        timeout: timeout,
        success: (res) => {
          if (res.statusCode === 200) {
            console.log(`[小程序下载] 成功: ${res.tempFilePath}`);
            resolve(res.tempFilePath);
          } else {
            reject(new Error(`下载失败，状态码: ${res.statusCode}`));
          }
        },
        fail: (error) => {
          console.error('[小程序下载] 失败:', error);
          reject(error);
        }
      });

      // 监听下载进度
      downloadTask.onProgressUpdate((progress) => {
        if (progress.progress % 20 === 0) { // 每20%打印一次
          console.log(`[小程序下载] 进度: ${progress.progress}%`);
        }
      });

      // 超时处理
      const timeoutId = setTimeout(() => {
        downloadTask.abort();
        reject(new Error('下载超时'));
      }, timeout);

      // 清理超时定时器
      const originalSuccess = downloadTask.success;
      const originalFail = downloadTask.fail;
      
      downloadTask.success = (res) => {
        clearTimeout(timeoutId);
        if (originalSuccess) originalSuccess(res);
      };
      
      downloadTask.fail = (error) => {
        clearTimeout(timeoutId);
        if (originalFail) originalFail(error);
      };
    });
  }

  /**
   * 获取缓存的视频
   */
  async get(videoUrl) {
    if (!this.cacheMap.has(videoUrl)) {
      this.performanceMetrics.cacheMisses++;
      return null;
    }

    const cacheInfo = this.cacheMap.get(videoUrl);
    
    // 验证临时文件是否仍然有效
    if (await this.isTempFileValid(cacheInfo)) {
      // 更新访问信息
      cacheInfo.lastAccessed = Date.now();
      cacheInfo.accessCount++;
      
      this.performanceMetrics.cacheHits++;
      return cacheInfo.tempFilePath;
    } else {
      // 临时文件无效，删除缓存
      await this.removeFromCache(videoUrl);
      this.performanceMetrics.cacheMisses++;
      return null;
    }
  }

  /**
   * 验证临时文件是否有效
   */
  async isTempFileValid(cacheInfo) {
    // 检查文件是否过期
    const age = Date.now() - cacheInfo.createdAt;
    if (age > this.tempFileExpire) {
      console.log('[小程序缓存] 临时文件已过期');
      return false;
    }

    // 小程序临时文件不能直接检查存在性，假设在过期时间内有效
    // 实际使用时会在视频组件加载时验证
    return true;
  }

  /**
   * 确保缓存空间
   */
  async ensureCacheSpace() {
    // 检查缓存数量
    if (this.cacheMap.size >= this.maxCacheCount) {
      await this.evictOldCache(1);
    }

    // 由于小程序无法准确获取文件大小，使用数量限制即可
  }

  /**
   * 清理旧缓存
   */
  async evictOldCache(count = 1) {
    const cacheEntries = Array.from(this.cacheMap.entries());
    
    // 按最后访问时间排序
    cacheEntries.sort((a, b) => a[1].lastAccessed - b[1].lastAccessed);

    // 清理最老的缓存
    for (let i = 0; i < count && i < cacheEntries.length; i++) {
      const [url] = cacheEntries[i];
      await this.removeFromCache(url);
      console.log(`[小程序缓存] 清理旧缓存: ${url}`);
    }
  }

  /**
   * 从缓存中删除
   */
  async removeFromCache(videoUrl) {
    if (this.cacheMap.has(videoUrl)) {
      this.cacheMap.delete(videoUrl);
      await this.saveCacheToStorage();
    }
  }

  /**
   * 清理过期缓存
   */
  async cleanExpiredCache() {
    const now = Date.now();
    const expiredKeys = [];
    
    for (const [url, cacheInfo] of this.cacheMap.entries()) {
      if (now - cacheInfo.createdAt > this.tempFileExpire) {
        expiredKeys.push(url);
      }
    }
    
    for (const url of expiredKeys) {
      await this.removeFromCache(url);
    }
    
    if (expiredKeys.length > 0) {
      console.log(`[小程序缓存] 清理过期缓存: ${expiredKeys.length} 个`);
    }
  }

  /**
   * 验证临时文件
   */
  async validateTempFiles() {
    const invalidKeys = [];
    
    for (const [url, cacheInfo] of this.cacheMap.entries()) {
      if (!(await this.isTempFileValid(cacheInfo))) {
        invalidKeys.push(url);
      }
    }
    
    for (const url of invalidKeys) {
      this.cacheMap.delete(url);
    }
    
    if (invalidKeys.length > 0) {
      console.log(`[小程序缓存] 清理无效临时文件: ${invalidKeys.length} 个`);
      await this.saveCacheToStorage();
    }
  }

  /**
   * 从本地存储加载缓存
   */
  async loadCacheFromStorage() {
    try {
      const cacheData = uni.getStorageSync(this.cacheStorageKey);
      if (cacheData && cacheData.cacheMap) {
        this.cacheMap = new Map(cacheData.cacheMap);
        this.performanceMetrics = { ...this.performanceMetrics, ...cacheData.performanceMetrics };
        console.log(`[小程序缓存] 从存储恢复 ${this.cacheMap.size} 个缓存记录`);
      }
    } catch (error) {
      console.warn('[小程序缓存] 加载存储失败:', error);
    }
  }

  /**
   * 保存缓存到本地存储
   */
  async saveCacheToStorage() {
    try {
      const cacheData = {
        cacheMap: Array.from(this.cacheMap.entries()),
        performanceMetrics: this.performanceMetrics,
        lastUpdated: Date.now()
      };
      
      uni.setStorageSync(this.cacheStorageKey, cacheData);
    } catch (error) {
      console.warn('[小程序缓存] 保存存储失败:', error);
    }
  }

  /**
   * 启动定时清理
   */
  startPeriodicCleanup() {
    // 每5分钟清理一次过期缓存
    setInterval(() => {
      this.cleanExpiredCache();
    }, 5 * 60 * 1000);
  }

  /**
   * 更新性能指标
   */
  updatePerformanceMetrics(downloadTime, success) {
    this.performanceMetrics.totalDownloadTime += downloadTime;
    
    if (success) {
      this.performanceMetrics.downloadSuccesses++;
    } else {
      this.performanceMetrics.downloadFailures++;
    }
  }

  /**
   * 获取缓存统计
   */
  getCacheStats() {
    const totalRequests = this.performanceMetrics.cacheHits + this.performanceMetrics.cacheMisses;
    const hitRate = totalRequests > 0 ? (this.performanceMetrics.cacheHits / totalRequests * 100) : 0;
    
    const totalDownloads = this.performanceMetrics.downloadSuccesses + this.performanceMetrics.downloadFailures;
    const averageDownloadTime = totalDownloads > 0 ? 
      (this.performanceMetrics.totalDownloadTime / totalDownloads) : 0;

    return {
      cacheCount: this.cacheMap.size,
      maxCacheCount: this.maxCacheCount,
      hitRate: hitRate.toFixed(2) + '%',
      averageDownloadTime: averageDownloadTime.toFixed(2) + 'ms',
      activeDownloads: this.activeDownloads,
      queueLength: this.downloadQueue.length,
      ...this.performanceMetrics
    };
  }

  /**
   * 暂停所有下载
   */
  pauseAllDownloads() {
    // 小程序下载任务暂停功能有限，主要清理队列
    this.downloadQueue = [];
    console.log('[小程序缓存] 已暂停所有下载队列');
  }

  /**
   * 清理旧缓存（内存警告时调用）
   */
  clearOldCache() {
    const cacheEntries = Array.from(this.cacheMap.entries());
    const toRemove = Math.ceil(cacheEntries.length / 2); // 清理一半
    
    cacheEntries
      .sort((a, b) => a[1].lastAccessed - b[1].lastAccessed)
      .slice(0, toRemove)
      .forEach(([url]) => {
        this.removeFromCache(url);
      });
    
    console.log(`[小程序缓存] 内存清理，删除 ${toRemove} 个缓存`);
  }

  /**
   * 预热缓存（批量下载重要视频）
   */
  async warmupCache(videoUrls, options = {}) {
    const { maxCount = 2 } = options; // 小程序限制并发数
    
    console.log(`[小程序缓存] 开始预热 ${Math.min(videoUrls.length, maxCount)} 个视频`);
    
    const priorityUrls = videoUrls.slice(0, maxCount);
    const promises = priorityUrls.map(url => 
      this.cache(url, { priority: 1 }).catch(error => {
        console.warn(`[小程序缓存] 预热失败: ${url}`, error);
        return null;
      })
    );
    
    await Promise.all(promises);
    console.log('[小程序缓存] 预热完成');
  }

  /**
   * 清空所有缓存
   */
  async clearAll() {
    this.cacheMap.clear();
    this.downloadQueue = [];
    
    // 重置性能指标
    this.performanceMetrics = {
      cacheHits: 0,
      cacheMisses: 0,
      downloadSuccesses: 0,
      downloadFailures: 0,
      totalDownloadTime: 0
    };
    
    await this.saveCacheToStorage();
    console.log('[小程序缓存] 所有缓存已清空');
  }

  /**
   * 获取下载进度状态
   */
  isDownloading(videoUrl) {
    return this.downloadingMap.has(videoUrl);
  }

  /**
   * 获取队列状态
   */
  getQueueStatus() {
    return {
      activeDownloads: this.activeDownloads,
      queueLength: this.downloadQueue.length,
      maxConcurrent: this.maxConcurrentDownloads
    };
  }
}

export default MiniProgramVideoCacheService;